package com.atguigu.realtime.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.realtime.common.GmallConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.client.Connection;
import redis.clients.jedis.Jedis;

/**
 * @author: 洛尘
 * @since: 2023-10-15 09:53
 * @description: 使用旁路缓存的方式优化查询维度数据
 *
 * 旁路缓存：
 *      如果在缓存中查找到了所需要的维度数据，那么直接作为方法的返回值返回（此情况称为缓存命中）。
 *      如果在缓存中没找到维度数据,那么到hbase中去查找相关维度数据，将查找结果放入缓存中，以便下次查找。
 *   产品选型：
 *      状态： 性能好，不好维护
 *      redis 性能也好，维护方便
 *   redis相关设置
 *          key： 维度表的表名+主键值
 *          数据类型: String
 *          expire:过期时间1天，避免冷数据常驻内存
 *          注意：如果维度数据发生了变化，那么缓存中的数据应该被删除
 *
 **/
public class DimUtil {
        public  static JSONObject getDimInfo(Jedis jedis, Connection connection, String nameSpace, String tableName, String id){
                //首先拿到redis的key
                String redisKey=tableName.toLowerCase()+":"+id;
                //设置用于接受redis查询到的数据
                String dimStr=null;
                //设置用于接受方法的返回值
                JSONObject dimjsonObject=null;
                //有可能获取不到相关值，拿到null值，所以try起来
                try {
                        dimStr = jedis.get(redisKey);
                        if (StringUtils.isNotEmpty(dimStr)){
                                System.out.println("~~~从redis中查询到了对应"+tableName+"表中的"+id+"维度数据~~~");
                                dimjsonObject= JSON.parseObject(dimStr);

                        }else {
                                //如果在缓存中没有找到要关联的维度，再发送请求到hbase进行查询
                                dimjsonObject= HbaseUtil.getDimInfoFromHbase(connection, nameSpace, tableName, id);
                                if (dimjsonObject!=null){
                                        System.out.println("~~~从hbase中查询到了对应"+tableName+"表中的"+id+"维度数据~~~");
                                        //将查询结果放入缓存中
                                        jedis.setex(redisKey,3600*24,dimjsonObject.toJSONString());
                                }else {
                                        System.out.println("~~~在Hbase中没有找到对应"+tableName+"表中的"+id+"维度数据~~~");
                                }
                        }

                } catch (Exception e) {
                        e.printStackTrace();
                        System.out.println("~~~从Redis中查询维度数据发生了异常~~~");
                }

                return dimjsonObject;
        }

        public static void main(String[] args) {
                Jedis jedis = RedisUtil.getRedisClient();
                Connection conn = HbaseUtil.getHbaseConnection();
                System.out.println(getDimInfo(jedis, conn, GmallConfig.HBASE_NAMESPACE, "dim_base_trademark", "2"));
                RedisUtil.closeRedisClient(jedis);
                HbaseUtil.closeHbaseConnection(conn);
        }

        public static void deleteCache(String tableName,String id){
                String redisKey=tableName.toLowerCase()+":"+id;
                Jedis jedis=null;
                try {
                        jedis=RedisUtil.getRedisClient();
                        jedis.del(redisKey);
                } catch (Exception e) {
                        e.printStackTrace();
                }finally {
                        if (jedis!=null){
                                System.out.println("~~~从Redis中清除缓存后，关闭Jedis~~~");
                                jedis.close();
                        }
                }
        }

}